package com.qfedu.aunt.commons.auth.config;
import com.qfedu.aunt.commons.auth.filter.TokenAuthFilter;
import com.qfedu.aunt.commons.auth.filter.TokenLoginFilter;
import com.qfedu.aunt.commons.auth.security.DefaultPasswordEncoder;
import com.qfedu.aunt.commons.auth.security.TokenLogoutHandler;
import com.qfedu.aunt.commons.auth.security.TokenManager;
import com.qfedu.aunt.commons.auth.security.UnauthEntryPoint;
import com.qfedu.aunt.commons.manager.RedisManager;
import com.qfedu.aunt.commons.service.impl.MyUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@SpringBootConfiguration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter {

    //token的生成解析以及删除类
    private TokenManager tokenManager;

    private RedisManager redisManager;

    //这个类的主要作用就是密码的散列
    private DefaultPasswordEncoder defaultPasswordEncoder;
    //这个就是 密码存储到数据库的 我们在使用的时候需要查询数据库 返回封装对象
    //目前还没没有
    private MyUserDetailService userDetailsService;

    //这里相当于一起将信息给注入进来
    @Autowired
    public TokenWebSecurityConfig(MyUserDetailService userDetailsService,
                                  DefaultPasswordEncoder defaultPasswordEncoder,
                                  TokenManager tokenManager,RedisManager redisManager) {
        this.userDetailsService = userDetailsService;
        this.defaultPasswordEncoder = defaultPasswordEncoder;
        this.tokenManager = tokenManager;
        this.redisManager=redisManager;
    }

    /**
     * 配置设置
     * @param http
     * @throws Exception
     */
    //设置退出的地址和token，redis操作地址
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(new UnauthEntryPoint())//没有权限访问
                .and().csrf().disable()  //关闭掉防止跨站点伪造的请求
                .authorizeRequests()
                .anyRequest().authenticated() //任何请求认证之后才能访问
                .and().logout().logoutUrl("/user/logout")//退出路径  这个路径是可以随便写的
                .addLogoutHandler(new TokenLogoutHandler(tokenManager)).and() //点击退出的时候处理器
                //添加认证的时候的过滤器
                //用户提交了用户名和密码之后就会执行到这里去
                .addFilter(new TokenLoginFilter(authenticationManager(), tokenManager,redisManager))
                //添加授权的的时候的过滤器
                //下面这个过滤器 只是干两件事情(1，判断是否已经登陆  判断是否有权限访问)
                .addFilter(new TokenAuthFilter(authenticationManager(), tokenManager,redisManager)).httpBasic();
    }

    //调用userDetailsService和密码处理
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        //重写这个方法的目的  就是将 我们访问数据库的类和 密码处理的类交给SpringSecurity去进行管理
        auth.userDetailsService(userDetailsService).passwordEncoder(defaultPasswordEncoder);
    }
    //不进行认证的路径，可以直接访问
    @Override
    public void configure(WebSecurity web) throws Exception {
        /**
         *    /*：表示的是以及路径  /**：表示的是多级路径
         */
        //web.ignoring().antMatchers("/user/login/");
    }
}
